using System;
using System.ComponentModel;
using System.Linq;
using System.Windows.Forms;
using Comteck.Timing;
using Comteck.Winforms.Extensions;
using DevExpress.XtraEditors.DXErrorProvider;

namespace Comteck.Winforms.Controls {

  #region event handle

  /// <summary>
  /// 在开始日期或结束日期发生变更后触发的事件
  /// </summary>
  /// <param name="sender"></param>
  /// <param name="e"></param>
  public delegate void MyDateRangeEditValueChangedEventHandler(object sender, EventArgs e);

  #endregion

  public partial class MyDateRangeEdit : UcBase {
    #region fields

    /// <summary>
    /// 在开始日期或结束日期发生变更后触发的事件
    /// </summary>
    [Category("功能扩展"), Description("在开始日期或结束日期发生变更后触发的事件"), ReadOnly(false)]
    public event MyDateRangeEditValueChangedEventHandler MyDateRangeEditValueChanged;
    #endregion

    public MyDateRangeEdit() {
      InitializeComponent();
    }
    #region properties

    /// <summary>
    /// 是否只读
    /// </summary>
    [DefaultValue(false), Category("功能扩展"), Description("是否只读"), ReadOnly(false)]
    public bool ReadOnly {
      get { return _readOnly; }
      set {
        _readOnly = value;

        ckBeginDate.ReadOnly = _readOnly;
        ckEndDate.ReadOnly = _readOnly;
        popEdit.ReadOnly = _readOnly;

        ckBeginDate.Properties.Buttons[0].Visible = !_readOnly;
        ckEndDate.Properties.Buttons[0].Visible = !_readOnly;
      }
    }
    private bool _readOnly;
    /// <summary>
    /// 非查询模式
    /// 如果是查询模式，则存在popedit按钮，否则则不存在
    /// </summary>
    [DefaultValue(true), Category("功能扩展"), Description("非查询模式"), ReadOnly(false)]
    public bool SearchMode {
      get { return _searchMode; }
      set {
        _searchMode = value;
        popEdit.Visible = _searchMode;
      }
    }
    private bool _searchMode = true;

    #region 开始时间

    /// <summary>
    /// 开始时间
    /// </summary>
    public DateTime BeginDate {
      get {
        return this.ckBeginDate.DateTime.Date;
      }
      set {
        ckBeginDate.DateTime = value;
      }
    }
    /// <summary>
    /// 结束时间
    /// </summary>
    public DateTime EndDate {
      get {
        return this.ckEndDate.DateTime.Date;
      }
      set {
        ckEndDate.DateTime = value;
      }
    }

    /// <summary>
    /// 设置最小日期
    /// </summary>
    /// <param name="minValue"></param>
    public void SetMinValue(DateTime minValue) {
      ckBeginDate.Properties.MinValue = ckEndDate.Properties.MinValue = minValue;
    }
    /// <summary>
    /// 设置最大日期
    /// </summary>
    /// <param name="maxValue"></param>
    public void SetMaxValue(DateTime maxValue) {
      ckBeginDate.Properties.MaxValue = ckEndDate.Properties.MaxValue = maxValue;
    }
    //private
    private DateTime dt = Clock.Now.Date;
    //上周
    private DateTime lastWeekStart = new DateTime();
    private DateTime lastWeekEnd = new DateTime();
    //本周
    private DateTime weekStart = new DateTime();
    private DateTime weekEnd = new DateTime();
    //上月
    private DateTime lastMonthStart = new DateTime();
    private DateTime LastMonthEnd = new DateTime();
    //本月
    private DateTime monthStart = new DateTime();
    private DateTime monthEnd = new DateTime();
    //上季
    private DateTime lastSeasonStart = new DateTime();
    private DateTime lastSeasonEnd = new DateTime();
    //当季
    private DateTime seasonStart = new DateTime();
    private DateTime seasonEnd = new DateTime();
    //下周
    private DateTime nextWeekStart = new DateTime();
    private DateTime nextWeekEnd = new DateTime();
    //下月
    private DateTime nextMonthStart = new DateTime();
    private DateTime nextMonthEnd = new DateTime();
    //下季
    private DateTime nextSeasonStart = new DateTime();
    private DateTime nextSeasonEnd = new DateTime();
    #endregion

    #endregion
    #region action
    /// <summary>
    /// 默认加载
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void MyDateRangeEdit_Load(object sender, EventArgs e) {
      ckBeginDate.EditValueChanged -= CkBeginDate_EditValueChanged;
      ckEndDate.EditValueChanged -= CkEndDate_EditValueChanged;
      if (this.DesignMode) return;
      InitDate();
      this.SetDate(dt, dt);
      ckBeginDate.EditValueChanged += CkBeginDate_EditValueChanged;
      ckEndDate.EditValueChanged += CkEndDate_EditValueChanged;

      if (this.ReadOnly) {
        ckBeginDate.ReadOnly = true;
        ckEndDate.ReadOnly = true;
        popEdit.ReadOnly = true;
      }

      if (this.SearchMode) {
        popEdit.Visible = true;
      } else {
        popEdit.Visible = false;
      }
    }
    /// <summary>
    /// 设置只读:
    /// 用处:合同续签
    /// </summary>
    public void SetReadOnly() {
      if (this.ReadOnly) {
        ckBeginDate.ReadOnly = true;
        ckEndDate.ReadOnly = true;
        popEdit.ReadOnly = true;
      }
    }
    /// <summary>
    /// 设置结束日期的延期
    /// 用处:合同延期
    /// </summary>
    public void SetEndDateMinValue(DateTime minValue) {
      ckBeginDate.ReadOnly = true;
      ckEndDate.Properties.MinValue = minValue;
      popEdit.ReadOnly = true;
    }

    private void lbNowDay_MouseHover(object sender, EventArgs e) {

    }
    /// <summary>
    /// 当天
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void lbNowDay_Click(object sender, EventArgs e) {
      this.SetDate(dt, dt);
      this.popDate.OwnerEdit.ClosePopup();
    }

    private void lblThreeDays_MouseHover(object sender, EventArgs e) {

    }
    /// <summary>
    /// 昨天
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void lblYearsterDay_Click(object sender, EventArgs e) {
      this.SetDate(dt.AddDays(-1), dt.AddDays(-1));
      this.popDate.OwnerEdit.ClosePopup();
    }
    /// <summary>
    /// 三天
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void lblThreeDays_Click(object sender, EventArgs e) {
      this.SetDate(dt.AddDays(-2), dt);
      this.popDate.OwnerEdit.ClosePopup();
    }

    private void lbNowWeek_MouseHover(object sender, EventArgs e) {

    }
    /// <summary>
    /// 上周
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void lblLastWeek_Click(object sender, EventArgs e) {
      this.SetDate(this.lastWeekStart, this.lastWeekEnd);
      this.popDate.OwnerEdit.ClosePopup();
    }
    /// <summary>
    /// 本周
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void lbNowWeek_Click(object sender, EventArgs e) {
      this.SetDate(this.weekStart, this.weekEnd);
      this.popDate.OwnerEdit.ClosePopup();
    }
    private void lbNowMonth_MouseHover(object sender, EventArgs e) {

    }

    /// <summary>
    /// 上月
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void lblLastMonth_Click(object sender, EventArgs e) {
      this.SetDate(this.lastMonthStart, this.LastMonthEnd);
      this.popDate.OwnerEdit.ClosePopup();
    }
    /// <summary>
    /// 当月
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void lbNowMonth_Click(object sender, EventArgs e) {
      this.SetDate(this.monthStart, this.monthEnd);
      this.popDate.OwnerEdit.ClosePopup();
    }
    /// <summary>
    /// 上季
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void lblLastSeason_Click(object sender, EventArgs e) {
      this.SetDate(this.lastSeasonStart, this.lastSeasonEnd);
      this.popDate.OwnerEdit.ClosePopup();
    }
    /// <summary>
    /// 当季
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void lblNowSeason_Click(object sender, EventArgs e) {
      this.SetDate(this.seasonStart, this.seasonEnd);
      this.popDate.OwnerEdit.ClosePopup();
    }

    /// <summary>
    /// 下周
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void lblNextWeek_Click(object sender, EventArgs e) {
      this.SetDate(this.nextWeekStart, this.nextWeekEnd);
      this.popDate.OwnerEdit.ClosePopup();
    }
    /// <summary>
    /// 下月
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void lblNextMonth_Click(object sender, EventArgs e) {
      this.SetDate(this.nextMonthStart, this.nextMonthEnd);
      this.popDate.OwnerEdit.ClosePopup();
    }
    /// <summary>
    /// 下季
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void lblNextSeason_Click(object sender, EventArgs e) {
      this.SetDate(this.nextSeasonStart, this.nextSeasonEnd);
      this.popDate.OwnerEdit.ClosePopup();
    }
    #endregion
    #region Function

    #region 自定义验证
    /// <summary>
    /// 自定义验证
    /// </summary>
    /// <param name="success">验证结果</param>
    /// <param name="msg">验证提示语</param>
    /// <param name="position">验证位置：1.开始日期，2.结束日期</param>
    /// <returns></returns>
    public bool SetdxValidationProvider(bool success, string msg,int[] position) {

      if (position.Contains(1)) {
        dxValidationProvider1.SetValidationRule(ckBeginDate, new AccountDayValidationRule {
          ErrorText = msg,
          ErrorType = ErrorType.Default,
          ValidateVlaue = success,
        });
      }
      if (position.Contains(2)) {
        dxValidationProvider1.SetValidationRule(ckEndDate, new AccountDayValidationRule {
          ErrorText = msg,
          ErrorType = ErrorType.Default,
          ValidateVlaue = success,
        });
      }
      return dxValidationProvider1.Validate();
    }
    private class AccountDayValidationRule : ValidationRule {
      public bool ValidateVlaue = true;
      public override bool Validate(Control control, object value) {
        return ValidateVlaue;
      }
    }
    #endregion
    /// <summary>
    /// 初始化标签时间
    /// </summary>
    private void InitDate() {
      var day = (int)dt.DayOfWeek;
      //保持中国人的习惯 一周就从周一开始吧
      day = day == 0 ? 7 : day;
      //当天
      this.lbNowDay.Text = $"当天:{dt.ToString("yyyy-MM-dd 00:00:00")}至{dt.ToString("yyyy-MM-dd 23:59:59")}";

      //昨天
      this.lblYearsterDay.Text = $"昨天:{dt.AddDays(-1).ToString("yyyy-MM-dd 00:00:00")}至{dt.AddDays(-1).ToString("yyyy-MM-dd 23:59:59")}";

      //三日（含今日）
      this.lbThreeDays.Text = $"三天:{dt.AddDays(-2).ToString("yyyy-MM-dd 00:00:00")}至{dt.ToString("yyyy-MM-dd 23:59:59")}";
      //上周
      this.lastWeekStart = dt.AddDays(-day - 7 + 1);
      this.lastWeekEnd = dt.AddDays(-day);
      this.lblLastWeek.Text = $"上周:{lastWeekStart.ToString("yyyy-MM-dd 00:00:00")}至{lastWeekEnd.ToString("yyyy-MM-dd 23:59:59")}";
      //本周
      this.weekStart = dt.AddDays(-day + 1);
      this.weekEnd = dt.AddDays(7 - day);
      this.lbNowWeek.Text = $"本周:{weekStart.ToString("yyyy-MM-dd 00:00:00")}至{weekEnd.ToString("yyyy-MM-dd 23:59:59")}";
      //上月
      this.lastMonthStart = dt.AddMonths(-1).AddDays(-dt.AddMonths(-1).Day + 1);
      this.LastMonthEnd = dt.AddDays(-dt.Day + 1).AddDays(-1);
      this.lblLastMonth.Text = $"上月:{lastMonthStart.ToString("yyyy-MM-dd 00:00:00")}至{LastMonthEnd.ToString("yyyy-MM-dd 23:59:59")}";

      //当月
      this.monthStart = dt.AddDays(-dt.Day + 1);
      this.monthEnd = dt.AddMonths(1).AddDays(-dt.AddMonths(1).Day + 1).AddDays(-1);
      this.lbNowMonth.Text = $"当月:{monthStart.ToString("yyyy-MM-dd 00:00:00")}至{monthEnd.ToString("yyyy-MM-dd 23:59:59")}";

      var season1 = dt.AddMonths(0 - ((dt.Month - 1) % 3));
      var season2 = dt.AddMonths((3 - ((dt.Month - 1) % 3) - 1));
      //上季
      this.lastSeasonStart = season1.AddDays(-season1.Day).AddMonths(-3).AddDays(+1);
      this.lastSeasonEnd = season1.AddDays(-season1.Day);
      this.lblLastSeason.Text = $"上季:{lastSeasonStart.ToString("yyyy-MM-dd 00:00:00")}至{lastSeasonEnd.ToString("yyyy-MM-dd 23:59:59")}";
      //当季

      this.seasonStart = season1.AddDays(-season1.Day + 1);
      this.seasonEnd = season2.AddMonths(1).AddDays(-season2.AddMonths(1).Day + 1).AddDays(-1);
      this.lblNowSeason.Text = $"当季:{seasonStart.ToString("yyyy-MM-dd 00:00:00")}至{seasonEnd.ToString("yyyy-MM-dd 23:59:59")}";
      ////下周
      //this.nextWeekStart = dt.AddDays(7 - day + 1);
      //this.nextWeekEnd = nextWeekStart.AddDays(6);
      //this.lblNextWeek.Text = $"下周:{nextWeekStart.ToString("yyyy-MM-dd 00:00:00")}至{nextWeekEnd.ToString("yyyy-MM-dd 23:59:59")}";
      //下月
      this.nextMonthStart = dt.AddMonths(1).AddDays(-dt.Day + 1);
      this.nextMonthEnd = nextMonthStart.AddMonths(1).AddDays(-1);
      this.lblNextMonth.Text = $"下月:{nextMonthStart.ToString("yyyy-MM-dd 00:00:00")}至{nextMonthEnd.ToString("yyyy-MM-dd 23:59:59")}";
      //下季
      this.nextSeasonStart = season2.AddMonths(1).AddDays(-season2.AddMonths(1).Day + 1);
      this.nextSeasonEnd = nextSeasonStart.AddMonths(3).AddDays(-1);
      this.lblNextSeason.Text = $"下季:{nextSeasonStart.ToString("yyyy-MM-dd 00:00:00")}至{nextSeasonEnd.ToString("yyyy-MM-dd 23:59:59")}";
    }
    /// <summary>
    /// 设置默认时间 并关闭
    /// </summary>
    /// <param name="_beginDate"></param>
    /// <param name="_endDate"></param>
    private void SetDate(DateTime _beginDate, DateTime _endDate) {
      this.ckBeginDate.DateTime = _beginDate.Date;
      this.ckEndDate.DateTime = _endDate.Date;
    }

    #endregion

    /// <summary>
    /// 起始日期发生变更
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void CkBeginDate_EditValueChanged(object sender, EventArgs e) {
      MyDateRangeEditValueChanged?.Invoke(sender, e);
    }
    /// <summary>
    /// 结束日期发生变更
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void CkEndDate_EditValueChanged(object sender, EventArgs e) {
      MyDateRangeEditValueChanged?.Invoke(sender, e);
    }
  }
}
